﻿// This software is the confidential and proprietary information of NetBay.
// Such confidential information should not be disclosed.
// NetBay copyright(c) 2012

#region

using System;
using System.IO;
using System.Linq;
using System.Reflection;

#endregion

namespace Rio.Workflow.Runtime.Interop
{
    public class WorkflowActivator
    {
        #region Class Methods

        /// <summary>
        /// Creates new instance from assembly and type
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="assemblyName">The assembly name</param>
        /// <param name="typeName">The type name</param>
        /// <returns>
        /// New instance of the specified
        /// </returns>
        public static T CreateInstance<T>(string assemblyName, string typeName)
        {
            try
            {
                //Get the assembly
                Assembly assembly = LoadAssembly(assemblyName);

                //Create instance of type name 
                object Obj = assembly.CreateInstance(typeName);
                if (Obj == null)
                {
                    throw new InvalidOperationException(string.Format("Cannot create new instance of {0}.", typeName));
                }
                return (T) Obj;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("WorkflowActivator CreateInstance failed, " + ex.Message, ex);
            }
        }

        /// <summary>
        /// Creates new instance from assembly and type
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="assembly">The assembly.</param>
        /// <param name="typeName">The type name</param>
        /// <returns>
        /// New instance of the specified
        /// </returns>
        public static T CreateInstance<T>(Assembly assembly, string typeName)
        {
            try
            {
                //Create instance of type name 
                object Obj = assembly.CreateInstance(typeName);
                if (Obj == null)
                {
                    throw new InvalidOperationException(string.Format("Cannot create new instance of {0}.", typeName));
                }
                return (T) Obj;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("WorkflowActivator CreateInstance failed, " + ex.Message, ex);
            }
        }

        /// <summary>
        /// Creates new instance from assembly and type
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type">The type.</param>
        /// <returns>
        /// New instance of the specified
        /// </returns>
        public static T CreateInstance<T>(Type type)
        {
            try
            {
                //Create instance of type name 
                object Obj = Activator.CreateInstance(type);
                if (Obj == null)
                {
                    throw new InvalidOperationException(string.Format("Cannot create new instance of {0}.", type.Name));
                }
                return (T) Obj;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("WorkflowActivator CreateInstance failed, " + ex.Message, ex);
            }
        }

        /// <summary>
        /// Gets the attribute.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="propertyInfo">The property info.</param>
        /// <returns>
        /// Return the custom attribut
        /// </returns>
        public static T GetAttribute<T>(PropertyInfo propertyInfo)
        {
            var attributes = propertyInfo.GetCustomAttributes(typeof (T), true);
            return (attributes.Length > 0) ? attributes.OfType<T>().First() : default(T);
        }

        /// <summary>
        /// If needed loads an assembly in the current application domain, then return it
        /// </summary>
        /// <param name="assemblyName">The assembly name</param>
        /// <returns></returns>
        public static Assembly LoadAssembly(string assemblyName)
        {
            Assembly assembly = null;
            try
            {
                //Get the assembly
                assembly = GetAssembly(assemblyName);

                //if not found we add the assembly in the current appdomain
                if (assembly == null)
                    assembly = AppDomain.CurrentDomain.Load(assemblyName);
            }
            catch (FileNotFoundException ex1)
            {
                throw new MissingAssemblyException("WorkflowActivator LoadAssembly failed, " + ex1.Message, ex1);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("WorkflowActivator LoadAssembly failed, " + ex.Message, ex);
            }
            return assembly;
        }

        /// <summary>
        /// Gets an assembly in the current app domain
        /// </summary>
        /// <param name="assemblyName">The assembly name</param>
        /// <returns>
        /// The assembly found, null if not found
        /// </returns>
        private static Assembly GetAssembly(string assemblyName)
        {
            Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies();
            for (int i = 0; i < ass.Length; i++)
            {
                if (ass[i].ManifestModule.Name.ToLower() == assemblyName.ToLower())
                {
                    return ass[i];
                }
            }
            return null;
        }

        #endregion
    }
}